<?php
/*
 * @Author: 杨红兵
 * @Date: 2021-10-19 08:48:24
 * @Last Modified by: 杨红兵
 * @Last Modified time: 2022-07-27 17:49:07
 */

namespace app\libraries\utils\log;

use app\libraries\utils\Trace;
use Monolog\DateTimeImmutable;
use Monolog\Logger as MonologLogger;
use Throwable;

class Logger extends MonologLogger
{
    /**
     * 获取当前请求的URL
     *
     * @Author YangHB
     * @DateTime 2021-10-28 13:43:58
     *
     * @return string
     */
    protected function getUrl(): string
    {
        $url = Trace::getInstance()->isCommand() ? Trace::getInstance()->getCommand() : Trace::getInstance()->getUrl();
        $url = empty(trim($url)) ? Trace::getInstance()->getUrl() : $url;
        return $url;
    }
    /**
     * Adds a log record.
     *
     * @param  int               $level    The logging level (a Monolog or RFC 5424 level)
     * @param  string            $message  The log message
     * @param  mixed[]           $context  The log context
     * @param  DateTimeImmutable $datetime Optional log date to log into the past or future
     * @return bool              Whether the record has been processed
     *
     * @phpstan-param Level $level
     */
    public function addRecord(int $level, string $message, array $context = [], DateTimeImmutable $datetime = null): bool
    {
        $record = null;
        // 日志信息封装
        $url = $this->getUrl();
        $timeSpan = time();
        $time = \DateTime::createFromFormat(
            '0.u00 U',
            microtime()
        )
            ->setTimezone(new \DateTimeZone(date_default_timezone_get()))->format('Y-m-d H:i:s');
        foreach ($this->handlers as $handler) {
            if (null === $record) {
                // skip creating the record as long as no handler is going to handle it
                if (!$handler->isHandling(['level' => $level])) {
                    continue;
                }

                $levelName = static::getLevelName($level);

                $record = [
                    'timestamp' => $timeSpan,
                    'microtime' => getmicrotime(),
                    'time' => $time,
                    'type' => strtolower($levelName),
                    'chan' => 'wechat_log',
                    'title' => 'easy_wechat',
                    'msg' => $message,
                    'message' => $message,
                    'content' => json_encode($context, JSON_UNESCAPED_UNICODE),
                    'level' => '' . $level,
                    'level_name' => $levelName,
                    'channel' => $this->name,
                    'project_name' => config('app.project_name'),
                    'env' => config('app.env'),
                    'run_env' => '' . getenv('POD_NODE_ENV'),
                    'run_pod' => '' . getenv('POD_NAMESPACE') . getenv('POD_NUMBER'),
                    'pod_name' => '' . getenv('POD_APPNAME'),
                    'server_name' => Trace::getInstance()->getHost(),
                    'url' => $url,
                    'grant_type' => Trace::getInstance()->getGrantType(),
                    'come_from' => Trace::getInstance()->getComeFrom(),
                    'all_trace_id' => Trace::getInstance()->getTraceId(),
                    'pretrace_id' => Trace::getInstance()->getPreTraceId(),
                    'now_trace_id' => Trace::getInstance()->getNowTraceId(),
                    //'extra' => [],
                ];

                try {
                    foreach ($this->processors as $processor) {
                        $record = $processor($record);
                    }
                } catch (Throwable $e) {
                    $this->handleException($e, $record);

                    return true;
                }
            }

            // once the record exists, send it to all handlers as long as the bubbling chain is not interrupted
            try {
                if (true === $handler->handle($record)) {
                    break;
                }
            } catch (Throwable $e) {
                $this->handleException($e, $record);

                return true;
            }
        }

        return null !== $record;
    }
}
